package org.hong.monkey.network.util;

import com.google.common.primitives.Ints;

public class TransportConf {
    private final String MONKEY_NETWORK_IO_MODE_KEY;
    private final String MONKEY_NETWORK_IO_PREFERDIRECTBUFS_KEY;
    private final String MONKEY_NETWORK_IO_CONNECTIONTIMEOUT_KEY;
    private final String MONKEY_NETWORK_IO_BACKLOG_KEY;
    private final String MONKEY_NETWORK_IO_NUMCONNECTIONSPERPEER_KEY;
    private final String MONKEY_NETWORK_IO_SERVERTHREADS_KEY;
    private final String MONKEY_NETWORK_IO_CLIENTTHREADS_KEY;
    private final String MONKEY_NETWORK_IO_RECEIVEBUFFER_KEY;
    private final String MONKEY_NETWORK_IO_SENDBUFFER_KEY;
    private final String MONKEY_NETWORK_SASL_TIMEOUT_KEY;
    private final String MONKEY_NETWORK_IO_MAXRETRIES_KEY;
    private final String MONKEY_NETWORK_IO_RETRYWAIT_KEY;
    private final String MONKEY_NETWORK_IO_LAZYFD_KEY;

    private final ConfigProvider conf;

    private final String module;

    public TransportConf(String module, ConfigProvider conf) {
        this.module = module;
        this.conf = conf;
        MONKEY_NETWORK_IO_MODE_KEY = getConfKey("io.mode");
        MONKEY_NETWORK_IO_PREFERDIRECTBUFS_KEY = getConfKey("io.preferDirectBufs");
        MONKEY_NETWORK_IO_CONNECTIONTIMEOUT_KEY = getConfKey("io.connectionTimeout");
        MONKEY_NETWORK_IO_BACKLOG_KEY = getConfKey("io.backLog");
        MONKEY_NETWORK_IO_NUMCONNECTIONSPERPEER_KEY =  getConfKey("io.numConnectionsPerPeer");
        MONKEY_NETWORK_IO_SERVERTHREADS_KEY = getConfKey("io.serverThreads");
        MONKEY_NETWORK_IO_CLIENTTHREADS_KEY = getConfKey("io.clientThreads");
        MONKEY_NETWORK_IO_RECEIVEBUFFER_KEY = getConfKey("io.receiveBuffer");
        MONKEY_NETWORK_IO_SENDBUFFER_KEY = getConfKey("io.sendBuffer");
        MONKEY_NETWORK_SASL_TIMEOUT_KEY = getConfKey("sasl.timeout");
        MONKEY_NETWORK_IO_MAXRETRIES_KEY = getConfKey("io.maxRetries");
        MONKEY_NETWORK_IO_RETRYWAIT_KEY = getConfKey("io.retryWait");
        MONKEY_NETWORK_IO_LAZYFD_KEY = getConfKey("io.lazyFD");
    }

    private String getConfKey(String suffix) {
        return "monkey." + module + "." + suffix;
    }

    public String ioMode() { return conf.get(MONKEY_NETWORK_IO_MODE_KEY, "NIO").toUpperCase(); }

    public boolean preferDirectBufs() {
        return conf.getBoolean(MONKEY_NETWORK_IO_PREFERDIRECTBUFS_KEY, true);
    }

    public int connectionTimeoutMs() {
        long defaultNetworkTimeoutS = JavaUtils.timeStringAsSec(
                conf.get("monkey.network.timeout", "120s"));
        long defaultTimeoutMs = JavaUtils.timeStringAsSec(
                conf.get(MONKEY_NETWORK_IO_CONNECTIONTIMEOUT_KEY, defaultNetworkTimeoutS + "s")) * 1000;
        return (int) defaultTimeoutMs;
    }

    public int numConnectionsPerPeer() {
        return conf.getInt(MONKEY_NETWORK_IO_NUMCONNECTIONSPERPEER_KEY, 1);
    }

    public int backLog() { return conf.getInt(MONKEY_NETWORK_IO_BACKLOG_KEY, -1); }

    public int serverThreads() { return conf.getInt(MONKEY_NETWORK_IO_SERVERTHREADS_KEY, 0); }

    public int clientThreads() { return conf.getInt(MONKEY_NETWORK_IO_CLIENTTHREADS_KEY, 0); }

    public int receiveBuf() { return conf.getInt(MONKEY_NETWORK_IO_RECEIVEBUFFER_KEY, -1); }

    public int sendBuf() { return conf.getInt(MONKEY_NETWORK_IO_SENDBUFFER_KEY, -1); }

    public int maxIORetries() { return conf.getInt(MONKEY_NETWORK_IO_MAXRETRIES_KEY, 3); }

    public int ioRetryWaitTimeMs() {
        return (int) JavaUtils.timeStringAsSec(conf.get(MONKEY_NETWORK_IO_RETRYWAIT_KEY, "5s")) * 1000;
    }

    public int memoryMapBytes() {
        return Ints.checkedCast(JavaUtils.byteStringAsBytes(
                conf.get("monkey.storage.memoryMapThreshold", "2m")));
    }

    public boolean lazyFileDescriptor() {
        return conf.getBoolean(MONKEY_NETWORK_IO_LAZYFD_KEY, true);
    }

    public int portMaxRetries() {
        return conf.getInt("monkey.port.maxRetries", 16);
    }
}
